/*
 * Copyright (c) 2002-2008 Universidade Federal de Campina Grande This program
 * is free software; you can redistribute it and/or modify it under the terms of
 * the GNU General Public License as published by the Free Software Foundation;
 * either version 2 of the License, or (at your option) any later version. This
 * program is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place, Suite 330, Boston, MA 02111-1307 USA
 */

package org.ourgrid.worker.collectors.gmond;

import java.io.IOException;
import java.net.Socket;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.ourgrid.worker.collectors.interfaces.WorkerCollectorController;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

import com.sun.org.apache.xpath.internal.XPathAPI;

public class CollectorThread implements Runnable {
	
	private static final int INTERVAL = 10 * 1000;
	
	private Thread thread;
	
	private WorkerCollectorController client;
	
	private Object lock;
	private boolean stoped;
	
	private String gmondAddress;
	private int gmondPort;
		
	public CollectorThread(WorkerCollectorController proxyClient, String gmondAddress, int gmondPort ) {
		thread = new Thread(this);
		this.client = proxyClient;
		this.gmondAddress = gmondAddress;
		this.gmondPort = gmondPort;
	}
	
	/**
	 * Starts the thread that collects all metrics from gmond daemon.
	 * @throws GMondCollectorException
	 */
	public void start() throws GMondCollectorException, IOException {
		startDeamon();
		lock = new Object();
		stoped = false;
		thread.start();
	}
	
	/**
	 * Stops the thread that collects all metrics from gmond daemon.
	 * @throws GMondCollectorException
	 */
	public void stop() throws GMondCollectorException {
		if( lock == null )
			throw new GMondCollectorException("GMond collector does not started yet.");
		synchronized (lock) {
			stoped = true;
		}
	}
	
	/**
	 * This method is implemented because this class implements Runnable interface. This method
	 * starts a loop that in each iteration it opens a socket with gmond daemon and collects
	 * all metrics provided by it.
	 */
	public void run() {
		
		while(true) {
			
			synchronized (lock) {
				if( stoped ) break;
			}
			
			try {
				Thread.sleep(INTERVAL);
				
				Socket gmondSocket = new Socket(gmondAddress, gmondPort);
				
				DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
				Document document = documentBuilder.parse(gmondSocket.getInputStream());
				NodeList nodeList = XPathAPI.eval(document, "//METRIC").nodelist();
				
				gmondSocket.close();
				
				client.metricsChanged(GMondUtils.generateMetricList(nodeList) );
				
			} catch(Exception e) {
				System.err.println("Could not connect to gmond socket.");
				e.printStackTrace();
				System.exit(-1);
			}
			
		}
		
	}
	
	private void startDeamon() throws GMondCollectorException, IOException {
		if( GMondUtils.getInstance().isGMondInstalled() ){
			if(!GMondUtils.getInstance().isGMondRunning()){
				try{
					GMondUtils.getInstance().startGMond();
				}catch(IOException ioe){
					throw new IOException("Could not start collector. I/O Error.");
				}
			}
		}else{
			throw new GMondCollectorException("Could not start worker monitor. Collector not installed.");
		}
	}

}
